#include <rtthread.h>
#include <rtdevice.h>
#include "littlevgl2rtt.h"
#include "lvgl.h"
#include "gui_app_fwk.h"

#include "app_clock_main.h"
#include "app_mem.h"

typedef struct {
    lv_obj_t *bg;
    lv_obj_t *hour_h;
    lv_obj_t *hour_l;
    lv_obj_t *minute_h;
    lv_obj_t *minute_l;
    lv_obj_t *line_top;
    lv_obj_t *line_bottom;
    lv_obj_t *heart;
    lv_obj_t *heart_text;
    lv_obj_t *heart_value;
    lv_obj_t *step;
    lv_obj_t *step_text;
    lv_obj_t *step_value;
    lv_timer_t *redraw_task;
    app_clock_time_t last_redraw_time;
    bool dirty;
} app_clock_wf1_t;

LV_IMG_DECLARE(img_wf1_bg_1);
LV_IMG_DECLARE(img_wf1_bg_2);
LV_IMG_DECLARE(img_wf1_bg_3);
LV_IMG_DECLARE(img_wf1_bg_4);
LV_IMG_DECLARE(img_wf1_bg_5);
LV_IMG_DECLARE(img_wf1_bg_6);
LV_IMG_DECLARE(img_wf1_bg_7);
LV_IMG_DECLARE(img_wf1_bg_8);
LV_IMG_DECLARE(img_wf1_bg_9);
LV_IMG_DECLARE(img_wf1_bg_10);
LV_IMG_DECLARE(img_wf1_bg_11);
LV_IMG_DECLARE(img_wf1_bg_12);
LV_IMG_DECLARE(img_wf1_bg_13);
LV_IMG_DECLARE(img_wf1_bg_14);
LV_IMG_DECLARE(img_wf1_bg_15);
LV_IMG_DECLARE(img_wf1_bg_16);
LV_IMG_DECLARE(img_wf1_bg_17);
LV_IMG_DECLARE(img_wf1_bg_18);
LV_IMG_DECLARE(img_wf1_bg_19);
LV_IMG_DECLARE(img_wf1_bg_20);
LV_IMG_DECLARE(img_wf1_bg_21);
LV_IMG_DECLARE(img_wf1_bg_22);
LV_IMG_DECLARE(img_wf1_bg_23);
LV_IMG_DECLARE(img_wf1_bg_24);
LV_IMG_DECLARE(img_wf1_bg_25);
LV_IMG_DECLARE(img_wf1_hour_0);
LV_IMG_DECLARE(img_wf1_hour_1);
LV_IMG_DECLARE(img_wf1_hour_2);
LV_IMG_DECLARE(img_wf1_hour_3);
LV_IMG_DECLARE(img_wf1_hour_4);
LV_IMG_DECLARE(img_wf1_hour_5);
LV_IMG_DECLARE(img_wf1_hour_6);
LV_IMG_DECLARE(img_wf1_hour_7);
LV_IMG_DECLARE(img_wf1_hour_8);
LV_IMG_DECLARE(img_wf1_hour_9);
LV_IMG_DECLARE(img_wf1_minute_0);
LV_IMG_DECLARE(img_wf1_minute_1);
LV_IMG_DECLARE(img_wf1_minute_2);
LV_IMG_DECLARE(img_wf1_minute_3);
LV_IMG_DECLARE(img_wf1_minute_4);
LV_IMG_DECLARE(img_wf1_minute_5);
LV_IMG_DECLARE(img_wf1_minute_6);
LV_IMG_DECLARE(img_wf1_minute_7);
LV_IMG_DECLARE(img_wf1_minute_8);
LV_IMG_DECLARE(img_wf1_minute_9);
LV_IMG_DECLARE(img_wf1_line_top);
LV_IMG_DECLARE(img_wf1_line_bottom);
LV_IMG_DECLARE(img_wf1_heart);
LV_IMG_DECLARE(img_wf1_step);

static app_clock_wf1_t *ui = NULL;

static const char *wf1_bg_imgs[] = {
    // clang-format off
    LV_EXT_IMG_GET(img_wf1_bg_1),  
    LV_EXT_IMG_GET(img_wf1_bg_2),  
    LV_EXT_IMG_GET(img_wf1_bg_3),
    LV_EXT_IMG_GET(img_wf1_bg_4), 
    LV_EXT_IMG_GET(img_wf1_bg_5),  
    LV_EXT_IMG_GET(img_wf1_bg_6),
    LV_EXT_IMG_GET(img_wf1_bg_7),  
    LV_EXT_IMG_GET(img_wf1_bg_8),  
    LV_EXT_IMG_GET(img_wf1_bg_9),
    LV_EXT_IMG_GET(img_wf1_bg_10), 
    LV_EXT_IMG_GET(img_wf1_bg_11), 
    LV_EXT_IMG_GET(img_wf1_bg_12),
    LV_EXT_IMG_GET(img_wf1_bg_13), 
    LV_EXT_IMG_GET(img_wf1_bg_14), 
    LV_EXT_IMG_GET(img_wf1_bg_15),
    LV_EXT_IMG_GET(img_wf1_bg_16), 
    LV_EXT_IMG_GET(img_wf1_bg_17), 
    LV_EXT_IMG_GET(img_wf1_bg_18),
    LV_EXT_IMG_GET(img_wf1_bg_19), 
    LV_EXT_IMG_GET(img_wf1_bg_20), 
    LV_EXT_IMG_GET(img_wf1_bg_21),
    LV_EXT_IMG_GET(img_wf1_bg_22), 
    LV_EXT_IMG_GET(img_wf1_bg_23), 
    LV_EXT_IMG_GET(img_wf1_bg_24),
    LV_EXT_IMG_GET(img_wf1_bg_25),
    // clang-format on
};

static const char *wf1_hour_imgs[] = {
    // clang-format off
    LV_EXT_IMG_GET(img_wf1_hour_0),
    LV_EXT_IMG_GET(img_wf1_hour_1),
    LV_EXT_IMG_GET(img_wf1_hour_2),
    LV_EXT_IMG_GET(img_wf1_hour_3),
    LV_EXT_IMG_GET(img_wf1_hour_4),
    LV_EXT_IMG_GET(img_wf1_hour_5),
    LV_EXT_IMG_GET(img_wf1_hour_6),
    LV_EXT_IMG_GET(img_wf1_hour_7),
    LV_EXT_IMG_GET(img_wf1_hour_8),
    LV_EXT_IMG_GET(img_wf1_hour_9),
    // clang-format on
};

static const char *wf1_minute_imgs[] = {
    // clang-format off
    LV_EXT_IMG_GET(img_wf1_minute_0),
    LV_EXT_IMG_GET(img_wf1_minute_1),
    LV_EXT_IMG_GET(img_wf1_minute_2),
    LV_EXT_IMG_GET(img_wf1_minute_3),
    LV_EXT_IMG_GET(img_wf1_minute_4),
    LV_EXT_IMG_GET(img_wf1_minute_5),
    LV_EXT_IMG_GET(img_wf1_minute_6),
    LV_EXT_IMG_GET(img_wf1_minute_7),
    LV_EXT_IMG_GET(img_wf1_minute_8),
    LV_EXT_IMG_GET(img_wf1_minute_9),
    // clang-format on
};

static void app_clock_wf1_redraw(lv_timer_t *task)
{
    app_clock_time_t current_time;
    rt_uint8_t hours, minutes;

    app_clock_main_get_current_time(&current_time);
    hours = current_time.h;
    minutes = current_time.m;

    if (ui->dirty) {
        lv_img_set_src(ui->hour_h, wf1_hour_imgs[hours / 10]);
        lv_img_set_src(ui->hour_l, wf1_hour_imgs[hours % 10]);
        lv_img_set_src(ui->minute_h, wf1_minute_imgs[minutes / 10]);
        lv_img_set_src(ui->minute_l, wf1_minute_imgs[minutes % 10]);
        ui->dirty = false;
    } else {
        if (ui->last_redraw_time.h == hours && ui->last_redraw_time.m == minutes) {
            return;
        }

        if (ui->last_redraw_time.h != hours) {
            if (ui->last_redraw_time.h / 10 != hours / 10) {
                lv_img_set_src(ui->hour_h, wf1_hour_imgs[hours / 10]);
            }
            if (ui->last_redraw_time.h % 10 != hours % 10) {
                lv_img_set_src(ui->hour_l, wf1_hour_imgs[hours % 10]);
            }
        }
        if (ui->last_redraw_time.m != minutes) {
            if (ui->last_redraw_time.m / 10 != minutes / 10) {
                lv_img_set_src(ui->minute_h, wf1_minute_imgs[minutes / 10]);
            }
            if (ui->last_redraw_time.m % 10 != minutes % 10) {
                lv_img_set_src(ui->minute_l, wf1_minute_imgs[minutes % 10]);
            }
        }
    }
    ui->last_redraw_time = current_time;
}

static void init_clock_number_img(void)
{
}

static void deinit_clock_number_img(void)
{
}

static rt_int32_t resume_callback(void)
{
    app_clock_wf1_redraw(NULL);

    if (NULL == ui->redraw_task) {
        ui->redraw_task = lv_timer_create(app_clock_wf1_redraw, 1000, (void *)0);
    }

    return RT_EOK;
}

static rt_int32_t pause_callback(void)
{
    lv_timer_del(ui->redraw_task);
    ui->redraw_task = NULL;
    ui->dirty = true;

    return RT_EOK;
}

static rt_int32_t init(lv_obj_t *parent)
{
    ui = (app_clock_wf1_t *)rt_malloc(sizeof(app_clock_wf1_t));
    memset(ui, 0, sizeof(app_clock_wf1_t));
    ui->dirty = true;

    lv_obj_t *my_parent = lv_obj_create(parent);

    lv_obj_set_size(my_parent, lv_obj_get_width(parent), lv_obj_get_height(parent));
    lv_obj_clear_flag(my_parent, LV_OBJ_FLAG_SCROLLABLE);

    ui->bg = lv_animimg_create(my_parent);
    lv_animimg_set_src(ui->bg, (lv_img_dsc_t **)wf1_bg_imgs,
                       sizeof(wf1_bg_imgs) / sizeof(wf1_bg_imgs[0]));
    lv_animimg_set_duration(ui->bg, 1000);
    lv_animimg_set_repeat_count(ui->bg, LV_ANIM_REPEAT_INFINITE);
    lv_obj_align(ui->bg, LV_ALIGN_CENTER, 0, 0);
    lv_animimg_start(ui->bg);

    ui->hour_h = lv_img_create(my_parent);
    lv_img_set_src(ui->hour_h, LV_EXT_IMG_GET(img_wf1_hour_0));
    lv_obj_set_pos(ui->hour_h, 18, 90);
    lv_obj_set_size(ui->hour_h, 118, 173);

    ui->hour_l = lv_img_create(my_parent);
    lv_img_set_src(ui->hour_l, LV_EXT_IMG_GET(img_wf1_hour_8));
    lv_obj_set_pos(ui->hour_l, 136, 30);
    lv_obj_set_size(ui->hour_l, 118, 173);

    ui->minute_h = lv_img_create(my_parent);
    lv_img_set_src(ui->minute_h, LV_EXT_IMG_GET(img_wf1_minute_2));
    lv_obj_set_pos(ui->minute_h, 136, 247);
    lv_obj_set_size(ui->minute_h, 118, 173);

    ui->minute_l = lv_img_create(my_parent);
    lv_img_set_src(ui->minute_l, LV_EXT_IMG_GET(img_wf1_minute_6));
    lv_obj_set_pos(ui->minute_l, 254, 187);
    lv_obj_set_size(ui->minute_l, 118, 173);

    ui->line_bottom = lv_img_create(my_parent);
    lv_img_set_src(ui->line_bottom, LV_EXT_IMG_GET(img_wf1_line_bottom));
    lv_obj_set_pos(ui->line_bottom, 30, 284);
    lv_obj_set_size(ui->line_bottom, 106, 106);

    ui->line_top = lv_img_create(my_parent);
    lv_img_set_src(ui->line_top, LV_EXT_IMG_GET(img_wf1_line_top));
    lv_obj_set_pos(ui->line_top, 254, 60);
    lv_obj_set_size(ui->line_top, 106, 106);

    ui->heart = lv_img_create(my_parent);
    lv_img_set_src(ui->heart, LV_EXT_IMG_GET(img_wf1_heart));
    lv_obj_set_pos(ui->heart, 60, 375);
    lv_obj_set_size(ui->heart, 29, 26);

    ui->heart_value = lv_label_create(my_parent);
    lv_label_set_text(ui->heart_value, "102");
    lv_obj_set_style_text_align(ui->heart_value, LV_TEXT_ALIGN_CENTER, 0);
    lv_obj_set_pos(ui->heart_value, 15, 300);
    lv_obj_set_size(ui->heart_value, 60, 25);

    ui->heart_text = lv_label_create(my_parent);
    lv_label_set_text(ui->heart_text, "bpm");
    lv_obj_set_style_text_align(ui->heart_text, LV_TEXT_ALIGN_CENTER, 0);
    lv_obj_set_pos(ui->heart_text, 15, 325);
    lv_obj_set_size(ui->heart_text, 60, 25);

    ui->step = lv_img_create(my_parent);
    lv_img_set_src(ui->step, LV_EXT_IMG_GET(img_wf1_step));
    lv_obj_set_pos(ui->step, 290, 55);
    lv_obj_set_size(ui->step, 29, 27);

    ui->step_text = lv_label_create(my_parent);
    // lv_label_set_text(ui->step_text, LV_EXT_STR_ID(step));
    lv_label_set_text(ui->step_text, "Step");
    lv_obj_set_style_text_align(ui->step_text, LV_TEXT_ALIGN_CENTER, 0);
    lv_obj_set_pos(ui->step_text, 300, 110);
    lv_obj_set_size(ui->step_text, 80, 25);

    ui->step_value = lv_label_create(my_parent);
    lv_label_set_text(ui->step_value, "8000");
    lv_obj_set_style_text_align(ui->step_value, LV_TEXT_ALIGN_CENTER, 0);
    lv_obj_set_pos(ui->step_value, 300, 135);
    lv_obj_set_size(ui->step_value, 80, 25);

    ui->redraw_task = NULL;

    return RT_EOK;
}

static rt_int32_t deinit(void)
{
    if (ui) {
        if (ui->redraw_task) {
            lv_timer_del(ui->redraw_task);
        }
        rt_free(ui);
        ui = NULL;
    }

    return RT_EOK;
}

static const app_clock_ops_t ops = {
    .init = init,
    .pause = pause_callback,
    .resume = resume_callback,
    .deinit = deinit,
};

void app_clock_wf1_register(void)
{
    app_clock_register("wf1", &ops);
}
